import React, { useState, useEffect } from 'react';
import { Viewer } from '@bytemd/react';
import { useHistory, useParams } from 'react-router-dom';
import highlight from '@bytemd/plugin-highlight';
import {
  Card,
  makeStyles,
  CircularProgress,
  Box,
  Button,
} from '@material-ui/core';
import ThumbUpIcon from '@material-ui/icons/ThumbUp';
import ChatBubbleIcon from '@material-ui/icons/ChatBubble';
import StarIcon from '@material-ui/icons/Star';
import { connect } from 'react-redux';
import Comment from './components/comment';
import {
  getPublishedArticleById,
  commentArticle,
  commentReply,
  likeArticleById,
  favoritedArticleById,
} from '../../api/actions/article';
import 'highlight.js/styles/github.css';

const plugins = [highlight()];

const useStyles = makeStyles((theme) => ({
  root: {
    width: '100%',
    // backgroundColor: theme.palette.background.paper,
  },
  inline: {
    display: 'inline',
  },
  viewer: {
    minHeight: 500,
    padding: theme.spacing(2),
  },
  actionBox: {
    marginTop: theme.spacing(2),
  },
  comment: {
    marginTop: theme.spacing(2),
  },
  commentCardHeaderAction: {
    margin: 0,
  },
  sendCommentIconButton: {
    width: 50,
    height: 50,
  },
  commentInput: {
    width: '98%',
  },
  timeAndAction: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
}));

function normalizeComments(comments) {
  const parentReg = /^((?!#).)*$/;
  if (Array.isArray(comments) && comments.length > 0) {
    const parents = comments.filter((comment) => parentReg.test(comment.key));
    parents.forEach((parent) => {
      const childrenReg = new RegExp(`^${parent.key}#.+`);
      // eslint-disable-next-line no-param-reassign
      parent.children = comments.map((comment) => {
        const { key } = comment;
        if (childrenReg.test(key)) {
          const matchDelimiter = key.match(/#/g);
          const delimiterCount = Array.isArray(matchDelimiter) ? matchDelimiter.length : 0;
          if (delimiterCount) {
            const parentKey = key.slice(0, key.lastIndexOf('#'));
            const findParent = comments.find((c) => c.key === parentKey);
            return {
              ...comment,
              parent: findParent,
            };
          }
          return {
            ...comment,
            parent,
          };
        } return undefined;
      }).filter((v) => v);
    });
    return parents;
  }
  return [];
}

const App = (props) => {
  const { user } = props;
  const { id } = useParams();
  const classes = useStyles();
  const history = useHistory();

  const [value, setValue] = useState();

  // 点赞相关state
  const [likeLoading, setLikeLoading] = useState(false);
  const [liked, setLiked] = useState([]);
  const [iLiked, setILiked] = useState(false);

  // 收藏相关state
  const [favoritedLoading, setFavoritedLoading] = useState(false);
  const [favorited, setFavorited] = useState([]);
  const [iFavorited, setIFavorited] = useState(false);

  // 评论相关state
  const [myComment, setMyComment] = useState('');
  const [comments, setComments] = useState([]);
  const [normalizedComments, setNormalizedComments] = useState([]);
  const [commentsLength, setCommentsLength] = useState(0);
  const [sendingComment, setSendingComment] = useState(false);

  const handleCommentInputChange = (value) => {
    setMyComment(value);
  };

  const handleSendComment = async () => {
    if (myComment) {
      setSendingComment(true);
      const res = await commentArticle({ content: myComment, pid: id });
      if (res.code === 0) {
        const _comments = [...comments];
        _comments.push({ ...res.data, name: user.name });
        setComments(_comments);
        setCommentsLength(_comments.length);
        setNormalizedComments(normalizeComments(_comments));
        setMyComment('');
      }
      setSendingComment(false);
    }
  };

  const handleSendCommentReply = async (parentKey, value) => {
    if (value) {
      const res = await commentReply({
        pid: id,
        content: value,
        parentKey,
      });
      if (res.code === 0) {
        const _comments = [...comments];
        _comments.push({ ...res.data, name: user.name });
        setComments(_comments);
        setCommentsLength(_comments.length);
        setNormalizedComments(normalizeComments(_comments));
      }
    }
  };

  const handleLikeClick = async () => {
    if (user) {
      setLikeLoading(true);
      const result = await likeArticleById({ id, userId: user.id });
      if (result.code === 0) {
        if (result.data.type === -1) {
          const findIndex = liked.indexOf(user.id);
          const _liked = [...liked];
          _liked.splice(findIndex, 1);
          setLiked(_liked);
          setILiked(false);
        } else if (result.data.type === 1) {
          const _liked = [...liked];
          _liked.push(user.id);
          setLiked(_liked);
          setILiked(true);
        }
      }
      setLikeLoading(false);
    } else {
      history.push('/signIn');
    }
  };

  const handleFavoriteClick = async () => {
    if (user) {
      setFavoritedLoading(true);
      const result = await favoritedArticleById({ id, userId: user.id });
      if (result.code === 0) {
        if (result.data.type === -1) {
          const findIndex = favorited.indexOf(user.id);
          const _favorited = [...favorited];
          _favorited.splice(findIndex, 1);
          setFavorited(_favorited);
          setIFavorited(false);
        } else if (result.data.type === 1) {
          const _favorited = [...favorited];
          _favorited.push(user.id);
          setFavorited(_favorited);
          setIFavorited(true);
        }
      }
      setFavoritedLoading(false);
    } else {
      history.push('/signIn');
    }
  };

  useEffect(() => {
    const fetchData = async () => {
      const res = await getPublishedArticleById({
        id,
      });
      if (res.code === 0) {
        setValue(res.data.post || '');
        setComments(res.data.comment || []);
        setCommentsLength((res.data.comment || []).length);
        setNormalizedComments(normalizeComments(res.data.comment || []));
        setLiked(res.data.liked || []);
        setFavorited(res.data.favorited || []);
        if (user) {
          // 设置点赞状态
          if (Array.isArray(res.data.liked)) {
            if (res.data.liked.indexOf(user.id) > -1) {
              setILiked(true);
            }
          }
          // 设置收藏状态
          if (Array.isArray(res.data.favorited)) {
            if (res.data.favorited.indexOf(user.id) > -1) {
              setIFavorited(true);
            }
          }
        }
      } else {
        history.push('/404');
      }
    };
    fetchData();
  }, []);

  return (
    <>
      <Card className={classes.viewer}>
        <Viewer value={value} plugins={plugins} />
      </Card>
      <Box className={classes.actionBox}>
        <Button
          color="primary"
          variant={iLiked ? 'contained' : 'text'}
          size="small"
          startIcon={
            likeLoading ? (
              <CircularProgress size={18} color="inherit" />
            ) : (
              <ThumbUpIcon />
            )
          }
          onClick={handleLikeClick}
        >
          {liked.length || 0}
        </Button>
        <Button size="small" disabled startIcon={<ChatBubbleIcon />}>
          {commentsLength}
        </Button>
        <Button
          onClick={handleFavoriteClick}
          color="primary"
          variant={iFavorited ? 'contained' : 'text'}
          size="small"
          startIcon={
            favoritedLoading ? (
              <CircularProgress size={18} color="inherit" />
            ) : (
              <StarIcon />
            )
          }
        >
          {iFavorited ? '已收藏' : '收藏'}
        </Button>
      </Box>
      <Comment
        user={user}
        comment={myComment}
        comments={normalizedComments}
        sendingComment={sendingComment}
        onCommentInputChange={handleCommentInputChange}
        onSendComment={handleSendComment}
        onSendCommentReply={handleSendCommentReply}
      />
    </>
  );
};

const mapStateToProps = (state) => ({
  user: state.user,
});

export default connect(mapStateToProps, null)(App);
